#ifndef SOULLANG_SOULC_LEXER_HPP
#define SOULLANG_SOULC_LEXER_HPP

#include <string>
#include <vector>
#include <memory>
#include <cstdint>

#include "codeAnalyze.hpp"
#include "errors.hpp"
#include "source.hpp"
#include "debug.hpp"

namespace soulc {
	/*
	 * keywords:
	 *		types: int uint ufloat string list
	 *		modifiers: const readonly public private protected exec funcs data oop
	 *		statments: if else while switch space or and try catch raise 
	 *		preprocessor: include import define template macro
	 * spec symbols:
	 *		= + - * / . , & : ; " ' ! % ( ) { } [ ]
	 */	

	typedef enum {
		KEYWORD_LEXEM_TYPE,
		IDENTIFIER_LEXEM_TYPE,
		SPEC_SYMBOL_LEXEM_TYPE,

		CONST_STR_LEXEM_TYPE,
		CONST_INT_LEXEM_TYPE,
		CONST_FLOAT_LEXEM_TYPE
	} LexemType;

	
	class Lexem {
	private:
		LexemType _type;
		
		std::string _text;
		char _symbol;
		int _integerConst;
		double _floatConst;
	public:
		Lexem(LexemType type);

		LexemType getType();
		
		std::string getText();
		void setText(std::string text);

		char getSymbol();
		void setSymbol(char symbol);

		int getIntegerConst();
		void setIntegerConst(int integerConst);

		double getFloatConst();
		void setFloatConst(double floatConst);
	};


	class Lexer {
	private:
		const std::vector<std::string> _keywords = {
			"package",
			"int", "uint", "float", "ufloat",
			"const", "readonly", "public", "private", "protected", "space", "exec", "data", "encaps", "inherit", "polymorphic",
			"if", "else", "or", "and", "while", "switch", "space", "try", "catch", "raise"
		};
		const std::vector<std::string> _preprocessorKeywords = {
			"import", "package", "define", "macro", "template", "included"
		};
		const std::vector<char> _specialSymbols = {'=', '+', '-', '*', '/', '.', ',', '&', ':', ';', '"', '\'', '!', '%', '(', ')', '{', '}', '[', ']', '?'};
	
		uint64_t getCharNoFromStringBeginning(std::string code, uint64_t absoluteCharNo);

	public:
		std::vector<std::shared_ptr<Lexem>> lexe(Source &source);
	};
}


#endif
